package com.htfyun.factorytest;

import android.Manifest;
import android.annotation.SuppressLint;
import android.app.AlertDialog;
import android.bluetooth.BluetoothAdapter;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.content.pm.PackageManager;
import android.net.wifi.WifiInfo;
import android.net.wifi.WifiManager;
import android.os.Build;
import android.os.Bundle;
import android.os.Handler;
import android.os.Message;
import android.os.SystemClock;
import android.telephony.TelephonyManager;
import android.text.SpannableString;
import android.text.Spanned;
import android.text.style.RelativeSizeSpan;
import android.text.style.StyleSpan;
import android.text.style.UnderlineSpan;
import android.util.SparseBooleanArray;
import android.view.Gravity;
import android.view.KeyEvent;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.view.WindowManager;
import android.widget.AdapterView;
import android.widget.ArrayAdapter;
import android.widget.Button;
import android.widget.FrameLayout;
import android.widget.GridView;
import android.widget.LinearLayout;
import android.widget.NumberPicker;
import android.widget.TextView;

import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.annotation.RequiresApi;
import androidx.core.app.ActivityCompat;
import androidx.core.content.ContextCompat;

import com.htfyun.eink.EinkUtils;
import com.htfyun.factorytest.agingtest.AgingTestItemAttr;
import com.htfyun.factorytest.common.BatteryCurrentThresholdEnum;
import com.htfyun.factorytest.common.BatteryInfo;
import com.htfyun.factorytest.common.Constants;
import com.htfyun.factorytest.common.FTUtils;
import com.htfyun.factorytest.common.ForeLightCtrl;
import com.htfyun.factorytest.common.LedCtrl_PX30;
import com.htfyun.factorytest.common.PermissionManager;
import com.htfyun.factorytest.common.SettingsUtils;
import com.htfyun.factorytest.config.Configuration;
import com.htfyun.factorytest.config.EinkProperty;
import com.htfyun.factorytest.config.HtfyunBuildConfig;
import com.htfyun.factorytest.config.NVRomKeys;
import com.htfyun.factorytest.config.OTATestConfig;
import com.htfyun.factorytest.config.PCCommand;
import com.htfyun.factorytest.device.DeviceAttr;
import com.htfyun.factorytest.engineer_test.EngineerActivity;
import com.htfyun.factorytest.factorytestui.FactoryMicTestActivity;
import com.htfyun.factorytest.factorytestui.FactoryTestItemsEnum;
import com.htfyun.factorytest.factorytestui.IFactoryTestItemSetListener;
import com.htfyun.factorytest.utils.DebugLog;
import com.htfyun.factorytest.utils.ShellUtils;
import com.htfyun.factorytest.utils.SystemPropertyUtil;
import com.htfyun.factorytest.utils.UsefulUtils;
import com.htfyun.factorytest.utils.WakeLockUtil;
import com.htfyun.factorytest.utils.executor.AppExecutors;

import java.lang.ref.WeakReference;
import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.List;

public class MainActivity extends FullScreenBaseActivity implements AdapterView.OnItemClickListener
        , AdapterView.OnItemLongClickListener, View.OnClickListener {

    private GridView gridList;
    private List<FactoryTestItemsEnum> itemsEnumList = new ArrayList<>();
    private DeviceAttr deviceAttr = DeviceAttr.getRunningDeviceAttr();

    private Context mContext;
    private TextView txtDesc;
    private TextView txtAgingResult;

    private Button btnQuit;
    private Button btnEmmc;
    private Button btnMemoryTest;
    private Button btnCpu;
    private Button btnEngineerTest;
    private Button btnDeviceInfo;

    private TextView txtVersion;
    private TextView txtProductVersion;
    private TextView txtRam;
    private TextView txtRom;

    private TextView txtSerialNo;
    private TextView txtImeiNo;
    private TextView txtImsiNo;
    private TextView txtMsisdn;
    private TextView txtWifiMac;
    private TextView textView;

    private TextView txtBatteryInfo;
    private TextView txtPCBAInfo;
    private TextView txtOta;

    private MyGridAdapter myGridAdapter;

    private BatteryInfo batteryInfo;

    private MyHandler myHandler;

    private boolean isPause = false;

    private View btnOtaTest;

    private boolean mAgingReceiverTag = false;

    //尝试解决: 多次调用 startActivityForResult 后, 会产生多个activity实例问题
    private SparseBooleanArray startActivityForResultMap = new SparseBooleanArray();

    private Configuration config = Configuration.getInstance();

    private TelephonyManager telephonyManager;

    @RequiresApi(api = Build.VERSION_CODES.O)
    @SuppressLint("StringFormatInvalid")
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        DebugLog.e("onCreate");
        //不要一直亮屏
        getWindow().clearFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON);

        SettingsUtils.setScreenOffTimeForFT(this);

        setContentView(R.layout.activity_main_factory_test);

        mContext = this;

        myHandler = new MyHandler(this);

        batteryInfo = new BatteryInfo(this);

        initView();

        initData();

        if (RootApplication.hasSIMCard) {
            checkDataIsEnabled();
        }

        registerAgingReceiver();

        updateItemByAfterAging(true);

        FTUtils.startFTFloat(this);

        initAllPermission();

        FactoryTestItemsEnum.addItemSetListener(itemSetListener);

        startActivityForResultMap.clear();

        EinkUtils.setWifiAutoOffTimeout(mContext, 5);

        WakeLockUtil.disableAutoPowerOff(mContext);
    }

    private void initView() {
        txtDesc = findViewById(R.id.txtDesc);
        txtAgingResult = findViewById(R.id.txtAgingResult);
        txtVersion = findViewById(R.id.txtVersion);

        txtSerialNo = findViewById(R.id.txtSerialNo);
        txtSerialNo.setOnClickListener(this);

        textView = findViewById(R.id.textView);
        textView.setOnClickListener(this);

        txtImeiNo = findViewById(R.id.txtImeiNo);
        txtImsiNo = findViewById(R.id.txtImsiNum);
        txtMsisdn = findViewById(R.id.txtMsisdn);
        txtWifiMac = findViewById(R.id.txtWifiMac);
        txtProductVersion = findViewById(R.id.txtProductVersion);
        txtRam = findViewById(R.id.txtRam);
        txtRom = findViewById(R.id.txtRom);
        txtBatteryInfo = findViewById(R.id.txtBatteryInfo);
        txtPCBAInfo = findViewById(R.id.txtPCBAInfo);
        txtOta = findViewById(R.id.txtOta);

//        if (RootApplication.hasSIMCard) {
//            txtImeiNo.setVisibility(View.VISIBLE);
//        }

        btnEmmc = findViewById(R.id.btnEmmcTest);
        btnEmmc.setTag(EmmcTestActivity.class);
        btnEmmc.setOnClickListener(this);

        btnMemoryTest = findViewById(R.id.btnMemoryTest);
        btnMemoryTest.setTag(MemoryTestActivity.class);
        btnMemoryTest.setOnClickListener(this);

        btnCpu = findViewById(R.id.btnCpuTest);
        btnCpu.setTag(CpuTestActivity.class);
        btnCpu.setOnClickListener(this);

        btnEngineerTest = findViewById(R.id.btnEngineerTest);
        btnEngineerTest.setTag(EngineerActivity.class);
        btnEngineerTest.setOnClickListener(this);

        btnQuit = findViewById(R.id.btnQuit);
        btnQuit.setOnClickListener(this);

        btnOtaTest = findViewById(R.id.btnOtaTest);
        btnOtaTest.setTag(OTATestActivity.class);
        btnOtaTest.setOnClickListener(this);

        gridList = findViewById(R.id.grid_list);
        gridList.setOnItemClickListener(this);
        gridList.setOnItemLongClickListener(this);

        itemsEnumList.clear();

        myGridAdapter = new MyGridAdapter(mContext, -1, itemsEnumList);

        gridList.setAdapter(myGridAdapter);

    }

    private void initData() {
        txtVersion.setText(getString(R.string.app_version, UsefulUtils.getAppVersion(mContext) + "-" + BuildConfig.BUILD_TYPE));
        txtProductVersion.setText(getString(R.string.firmware_version, EinkProperty.getProductVersion()));

        AppExecutors.runOnIoThread(() -> {
            String ramString = getString(R.string.ram_test_result, UsefulUtils.getRamNominalSize(), getRamResult());
            String romString = getString(R.string.rom_test_result, UsefulUtils.getRomNominalSize(), getRomResult());
            AppExecutors.postToMainThread(() -> {
                txtRam.setText(getSpannableString(ramString));
                txtRom.setText(getSpannableString(romString));
            });
        });
//        DebugLog.e("app_version = " + txtVersion.getText());
//        DebugLog.e("serialNo = " + txtSerialNo.getText());
//        DebugLog.e("ImeiNo = " + txtImeiNo.getText());
//        DebugLog.e("firmware_version = " + txtProductVersion.getText());
    }

    private void updateOTATxt() {

        if (OTATestConfig.isEssentialForOTATest(mContext)) {

            String pass = getString(R.string.test_result_pass);
            String fail = getString(R.string.test_result_fail);

            if (OTATestConfig.isOTAStarted(mContext)) {
                OTATestConfig.setOTAStarted(mContext, false);
                boolean isUpgrade = EinkUtils.isOTAUpgrade(mContext);
                FactoryTestItemsEnum.ota.setResult(mContext, isUpgrade ? pass : fail);
                OTATestConfig.setOTAPassed(mContext, isUpgrade);
            }

            boolean isOTAPassed = FactoryTestItemsEnum.ota.isPassed(mContext);
            String result = getString(R.string.ota_test_result, isOTAPassed ? pass : fail);
            txtOta.setText(getSpannableString(result));

            txtOta.setVisibility(View.VISIBLE);

        } else {

            txtOta.setVisibility(View.GONE);

        }
    }

    private IFactoryTestItemSetListener itemSetListener = (key, result) -> EinkProperty.setEinkFTTestAllResultPassed(FTUtils.isFTPassed());

    private String getRamResult() {
        BigDecimal definedRamSize = new BigDecimal(UsefulUtils.getDefinedRamSize());
        BigDecimal realRamSize = new BigDecimal(UsefulUtils.getRamTotalSize());
        String result = getString(realRamSize.compareTo(definedRamSize) > 0 ? R.string.test_result_pass : R.string.test_result_fail);
        FactoryTestItemsEnum.ram.setResult(mContext, result);
        return result;
    }

    private String getRomResult() {
        BigDecimal definedRomSize = BigDecimal.valueOf(UsefulUtils.getDefinedRomSize());
        BigDecimal realRomSize = BigDecimal.valueOf(UsefulUtils.getRomTotalSize());
        String result = getString(realRomSize.compareTo(definedRomSize) > 0 ? R.string.test_result_pass : R.string.test_result_fail);
        FactoryTestItemsEnum.rom.setResult(mContext, result);
        return result;
    }

    @RequiresApi(api = Build.VERSION_CODES.O)
    @Override
    protected void onResume() {
        super.onResume();
        DebugLog.e("onResume");

        if (RootApplication.hasSIMCard) {
            txtImeiNo.setText(getString(R.string.imeino,getImeiNumber()));
            myHandler.removeMessages(MyHandler.MSG_GET_IMEI);
            myHandler.sendEmptyMessage(MyHandler.MSG_GET_IMEI);

            txtMsisdn.setText("getting...");
            myHandler.removeMessages(MyHandler.MSG_GET_MSISDN);
            myHandler.sendEmptyMessage(MyHandler.MSG_GET_MSISDN);

            txtImsiNo.setText(getString(R.string.imsi_num) + getSimIMSI(this));
        }

        txtWifiMac.setText(getString(R.string.wifi_mac) + getWifiMacAddress(this));

        EinkUtils.setFastSleepTimeout("0");
        EinkUtils.setFastSleepTimeout(mContext, 150);

        txtSerialNo.setText(getString(R.string.serialno, EinkProperty.getSerialNumber()));
        updateOTATxt();

        String infoString = mContext.getString(R.string.pcba_test_result, FactoryTestItemsEnum.pcba.getResult(mContext));
        txtPCBAInfo.setText(getSpannableString(infoString));

        isPause = false;

        batteryInfo.setOnBatteryChangedListener(onBatteryChangedListener);
        batteryInfo.startMonitor();

        if (FTUtils.isInAgingTest(mContext)) {

            DebugLog.e("start aging test activity");
            myHandler.sendEmptyMessage(MyHandler.MSG_START_AGING);

        } else if (HtfyunBuildConfig.TEST_AGING_WITHOUT_SCREEN) {

            myHandler.sendEmptyMessageDelayed(MyHandler.MSG_CHECK_AGING, MyHandler.DELAY_CHECK_AGING);

        }

        if (PCCommand.isFromPCBroadcast(mContext)) {
            PCCommand.clearFromPCBroadcast(mContext);
        }

        updateMainUI();

        startLedCtrl();

        if (FactoryTestItemsEnum.pcba.isPassed(mContext)) {
            FTFloatWindowService.setPCBABtnShow(false);
            gridList.setVisibility(View.VISIBLE);
            txtAgingResult.setVisibility(View.VISIBLE);
        } else {
            FTFloatWindowService.setPCBABtnShow(true);
            gridList.setVisibility(View.INVISIBLE);
            txtAgingResult.setVisibility(View.GONE);
        }

        //前光中等亮度
        if (deviceAttr.hasForeLight()) {
            ForeLightCtrl.setBrightMiddle(mContext);
        }

    }

    //检查数据开关是否打开
    private void checkDataIsEnabled(){
        if(telephonyManager == null){
            telephonyManager = (TelephonyManager) getSystemService(Context.TELEPHONY_SERVICE);
        }

        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
            if(!telephonyManager.isDataEnabled()){
                telephonyManager.setDataEnabled(true);
            }
        }
    }

    @RequiresApi(api = Build.VERSION_CODES.O)
    private String getImeiNumber() {
        if (ActivityCompat.checkSelfPermission(this, Manifest.permission.READ_PHONE_STATE) != PackageManager.PERMISSION_GRANTED) {
            PermissionManager.getInstance(getApplicationContext()).execute(this, Manifest.permission.READ_PHONE_STATE);
        }
        String imei = telephonyManager.getImei();
        String imei_customer = SystemPropertyUtil.getSystemProperty("pv.ro.eink.imei.customer");
        if (imei == null) {
            DebugLog.e("imei = null");
            return getString(R.string.imei_no_unknown);
        }
        if ("".equals(SystemPropertyUtil.getSystemProperty("ro.imei.no"))) {
            SystemPropertyUtil.setSystemProperty("ro.imei.no", imei);
        }
        if (imei_customer.isEmpty()) {
            DebugLog.e("pv.ro.eink.imei.customer is empty");
            return imei;
        }
        if (imei.equals(imei_customer)) {
            return imei;
        } else {
            DebugLog.e("imei != imei_customer");
            return getString(R.string.imei_no_error);
        }

    }

    /**
     * 获取IMSI, 国际移动用户识别号
     */
    private String getSimIMSI(Context context){
        if (ActivityCompat.checkSelfPermission(context, Manifest.permission.READ_PHONE_STATE) == PackageManager.PERMISSION_GRANTED) {
            String imsi = telephonyManager.getSubscriberId();
            if (imsi != null) {
                return imsi;
            }
        }
        return "";
    }

    /**
     * 获取电话号码
     */
    public static String getSimNumber(Context context){
        TelephonyManager telephonyManager = (TelephonyManager) context.getSystemService(Context.TELEPHONY_SERVICE);
        if (ActivityCompat.checkSelfPermission(context, Manifest.permission.READ_PHONE_STATE) == PackageManager.PERMISSION_GRANTED) {
            String simNumber = telephonyManager.getLine1Number();
            if (simNumber != null) {
                return simNumber;
            }
        }
        return "";
    }

    /**
     * 获取WIFI MAC地址
     */
    public static String getWifiMacAddress(Context context) {
        String defaultMac = "02:00:00:00:00:00"; //无法正常获取mac地址
        try {
            WifiManager wifiManager = (WifiManager) context.getSystemService(Context.WIFI_SERVICE);
            if(wifiManager != null){
                WifiInfo wifiInfo = wifiManager.getConnectionInfo();
                if (wifiInfo != null) {
                    String macAddress = wifiInfo.getMacAddress();
                    if(macAddress != null){
                        return macAddress;
                    }
                }
            }
        } catch (Exception e) {
            e.printStackTrace();
            return defaultMac;
        }
        return defaultMac;
    }

    private void checkIfStartAging() {
        if (!FactoryTestItemsEnum.aging.isPassed(this)) {
            DebugLog.e("start aging test activity.");
            FactoryTestItemsEnum itemsEnum = FactoryTestItemsEnum.aging;
            Intent intent = new Intent(mContext, itemsEnum.getItemClass());
            startActivityForResult(intent, itemsEnum.getIdentify());
        }
    }

    @Override
    protected void onPause() {
        super.onPause();
        DebugLog.e("onPause");
        isPause = true;

        myHandler.removeMessages(MyHandler.MSG_GET_IMEI);
        myHandler.removeMessages(MyHandler.MSG_GET_MSISDN);

        batteryInfo.setOnBatteryChangedListener(null);
        batteryInfo.stopMonitor();

        stopLedCtrl();

        EinkUtils.setFastSleepTimeout(mContext, 0XFE);
        if (deviceAttr.hasForeLight()) {
            ForeLightCtrl.setBrightMin(mContext);
        }

    }

    @Override
    protected void onDestroy() {
        super.onDestroy();
        DebugLog.e("onDestroy");

        unregisterAgingReceiver();
        EinkUtils.setFastSleepTimeout("15");
        EinkUtils.setWifiAutoOffTimeout(mContext, 240);
        FactoryTestItemsEnum.removeItemSetListener(itemSetListener);

        startActivityForResultMap.clear();
    }

    @Override
    public void startActivityForResult(Intent intent, int requestCode) {

        if (requestCode != REQUEST_CODE_USING_BTN) {
            Boolean started = startActivityForResultMap.get(requestCode);
            if (started != null && started) {
                return;
            }

            startActivityForResultMap.put(requestCode, true);
        }

        DebugLog.e("startActivityForResult, requestCode = " + requestCode + ", intent = " + intent);

        super.startActivityForResult(intent, requestCode);
    }

    @Override
    protected void onActivityResult(int requestCode, int resultCode, Intent data) {
        super.onActivityResult(requestCode, resultCode, data);
        DebugLog.e("onActivityResult requestCode = " + requestCode + ", resultCode = " + resultCode);

        startActivityForResultMap.delete(requestCode);

        FactoryTestItemsEnum itemsEnum = FactoryTestItemsEnum.getItemEnumByIdentify(requestCode);

        if (itemsEnum == null) {
            return;
        }
        String result = getString(R.string.test_result_unknown);
        if (resultCode == RESULT_OK) {
            result = getString(R.string.test_result_pass);
        } else if (resultCode == RESULT_CANCELED) {
            result = getString(R.string.test_result_fail);
        }

        FactoryTestItemsEnum agingItemsEnum = FactoryTestItemsEnum.aging;

        DebugLog.e("itemsEnum = " + (itemsEnum));

        if (itemsEnum != agingItemsEnum && agingItemsEnum.isPassed(mContext)) {

            itemsEnum.setResultForAfterAging(mContext, result);
            for (String item : itemsEnum.getNVRomKey()) {
                //无电磁屏 config.ini只写入触摸屏结果
                if (!DeviceAttr.getRunningDeviceAttr().isExistETP() && NVRomKeys.KEY_FT_ELECTRIC_TP.equals(item)) {
                    continue;
                }
                //无触摸屏 config.ini只写入电磁屏结果
                if (!DeviceAttr.getRunningDeviceAttr().isExistTP() && NVRomKeys.KEY_FT_FINGER_TP.equals(item)) {
                    continue;
                }
                config.setConfig(Constants.SECTION_FUNCTION_TEST_AGING, itemsEnum.newNVRomKeyForAfterAging(item), Constants.PASS.equals(result) ? "1" : "0");

            }
            config.setConfig(Constants.SECTION_FUNCTION_TEST_AGING, Constants.SECTION_FUNCTION_TEST_AGING, FTUtils.isFactoryTestItemsAfterAgingAllPassed() ? "1" : "0");
        } else {
            itemsEnum.setResult(mContext, result);
            if (itemsEnum != agingItemsEnum) {
                for (String item : itemsEnum.getNVRomKey()) {
                    //无电磁屏 config.ini只写入触摸屏结果
                    if (!DeviceAttr.getRunningDeviceAttr().isExistETP() && NVRomKeys.KEY_FT_ELECTRIC_TP.equals(item)) {
                        continue;
                    }
                    //无触摸屏 config.ini只写入电磁屏结果
                    if (!DeviceAttr.getRunningDeviceAttr().isExistTP() && NVRomKeys.KEY_FT_FINGER_TP.equals(item)) {
                        continue;
                    }
                    config.setConfig(Constants.SECTION_FUNCTION_TEST, item, Constants.PASS.equals(result) ? "1" : "0");
                }
            }
            config.setConfig(Constants.SECTION_FUNCTION_TEST, Constants.SECTION_FUNCTION_TEST, FTUtils.isFactoryTestItemsAllPassedExcludeAging() ? "1" : "0");
        }
        if (itemsEnum == agingItemsEnum) {
            itemsEnum.setResultForLog(mContext, FTUtils.getAgingResultInfo(mContext));
            config.setConfig(Constants.SECTION_AGING, agingItemsEnum.getNVRomKey()[0], Constants.PASS.equals(result) ? "1" : "0");
        }

        updateMainUI();

    }

    private boolean isAllGotPermission() {
        return !((ContextCompat.checkSelfPermission(this, Manifest.permission.ACCESS_FINE_LOCATION) != PackageManager.PERMISSION_GRANTED
                || ContextCompat.checkSelfPermission(this, Manifest.permission.ACCESS_COARSE_LOCATION) != PackageManager.PERMISSION_GRANTED
                || ContextCompat.checkSelfPermission(this, Manifest.permission.RECORD_AUDIO) != PackageManager.PERMISSION_GRANTED
                || ContextCompat.checkSelfPermission(this, Manifest.permission.WRITE_SETTINGS) != PackageManager.PERMISSION_GRANTED
                || ContextCompat.checkSelfPermission(this, Manifest.permission.WRITE_EXTERNAL_STORAGE) != PackageManager.PERMISSION_GRANTED)
        );
    }

    private void initAllPermission() {

        if (isAllGotPermission()) {
            return;
        }

        //同时申请多个权限
        PermissionManager.getInstance(getApplicationContext()).execute(this,
                Manifest.permission.ACCESS_FINE_LOCATION,
                Manifest.permission.ACCESS_COARSE_LOCATION,
                Manifest.permission.RECORD_AUDIO,
                Manifest.permission.WRITE_SETTINGS,
                Manifest.permission.WRITE_EXTERNAL_STORAGE);
    }

    @Override
    public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions,
                                           @NonNull int[] grantResults) {
        super.onRequestPermissionsResult(requestCode, permissions, grantResults);
        PermissionManager.getInstance(getApplicationContext()).
                onRequestPermissionsResult(requestCode, permissions, grantResults);
    }

    private void updateMainUI() {

        EinkProperty.setEinkFTTestAllResultPassed(FTUtils.isFTPassed());

        if (isPause) {
            return;
        }

//        if (FTUtils.isFactoryTestItemsAllPassedExcludeNoActivity()) {
        if (!FactoryTestItemsEnum.pcba.isPassed(mContext)) {
            txtDesc.setText(R.string.desc_before_pcba);
        } else if (FactoryTestItemsEnum.aging.isPassed(mContext)) {

            txtDesc.setText(R.string.desc_after_aging);

            if (btnOtaTest != null) {
                btnOtaTest.setVisibility(View.GONE);
            }

        } else {

            txtDesc.setText(R.string.desc_before_aging);

        }
        final SpannableString msp = getSpannableString(FTUtils.getAgingResultInfo(mContext));
        txtAgingResult.setText(msp);
        updateItemByAfterAging();

    }


    @NonNull
    private SpannableString getSpannableString(String infoString) {
        final SpannableString msp = new SpannableString(infoString);
        String resultSearch = getString(R.string.ft_use_result_for_search);
        String pass = getString(R.string.test_result_pass);
        int index = infoString.indexOf(resultSearch);
        if (index > 0) {
            int len = index + resultSearch.length() + pass.length();
            if (len > infoString.length()) {
                len = infoString.length();
            }

            msp.setSpan(new RelativeSizeSpan(1.2f), index, len, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
            msp.setSpan(new StyleSpan(android.graphics.Typeface.BOLD_ITALIC), index, len, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
            msp.setSpan(new UnderlineSpan(), index, len, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
        }
        return msp;
    }

    private String getResultByCheckFactoryTestItemsEnum(FactoryTestItemsEnum itemsEnum,
                                                        boolean pass) {

        String result = itemsEnum.getResultForAfterAging(mContext);

        if (FTUtils.isFactoryTestItemsAllPassed() && itemsEnum.isKeepTestAfterAging()) {

            if (pass && !itemsEnum.isPassedForAfterAging(mContext)) {
                result = mContext.getString(R.string.test_result_pass);

                itemsEnum.setResultForAfterAging(mContext, result);

            }

            return result;
        }

        result = itemsEnum.getResult(mContext);

        if (pass && !itemsEnum.isPassed(mContext)) {
            result = mContext.getString(R.string.test_result_pass);

            itemsEnum.setResult(mContext, result);

            updateMainUI();
        }

        return result;

    }

    private void updateItemByAfterAging() {

        updateItemByAfterAging(false);
    }

    private void updateItemByAfterAging(boolean force) {

//        if (FTUtils.isFactoryTestItemsAllPassed() ) {
        if (FactoryTestItemsEnum.aging.isPassed(mContext)) {

            if (!myGridAdapter.isUseResultOfAfterAging() || force) {

                itemsEnumList.clear();

                myGridAdapter.setUseResultOfAfterAging(true);

                for (FactoryTestItemsEnum item : FactoryTestItemsEnum.values()) {

                    DebugLog.d("DeviceAttr: " + item);

                    if (isContinue(item)) continue;

                    if (item.isKeepTestAfterAging() && item.getItemClass() != null) {
                        itemsEnumList.add(item);
                    }
                }

            }

        } else {

            if (myGridAdapter.isUseResultOfAfterAging() || force) {
                itemsEnumList.clear();

                myGridAdapter.setUseResultOfAfterAging(false);

                for (FactoryTestItemsEnum item : FactoryTestItemsEnum.values()) {

                    DebugLog.d("DeviceAttr: " + item);

                    if (isContinue(item)) continue;

                    if (item.getItemClass() != null) {
                        itemsEnumList.add(item);
                    }
                }

            }
        }

        myGridAdapter.notifyDataSetChanged();

    }

    public static boolean isContinue(FactoryTestItemsEnum item) {
        if (item == FactoryTestItemsEnum.bluetooth && BluetoothAdapter.getDefaultAdapter() == null) {
            return true;
        }

        if (item == FactoryTestItemsEnum.camera && !DeviceAttr.getRunningDeviceAttr().hasCamera()) {
            return true;
        }

        if (item == FactoryTestItemsEnum.fingerPrint && !DeviceAttr.getRunningDeviceAttr().hasFingerprint()) {
            return true;
        }

//        if (item == FactoryTestItemsEnum.simCard && !RootApplication.hasSIMCard) {
//            return true;
//        }

        if (item == FactoryTestItemsEnum.sdcard && !DeviceAttr.getRunningDeviceAttr().hasSDCard()) {
            return true;
        }

        if (item == FactoryTestItemsEnum.otg && !DeviceAttr.getRunningDeviceAttr().hasOtg()) {
            return true;
        }

        if (item == FactoryTestItemsEnum.versionInfo && !DeviceAttr.getRunningDeviceAttr().hasVersionInfo()) {
            return true;
        }

        if (item == FactoryTestItemsEnum.penAccuracy && !DeviceAttr.getRunningDeviceAttr().hasPenAccuracy()) {
            return true;
        }

        if (item == FactoryTestItemsEnum.wifi && !DeviceAttr.getRunningDeviceAttr().hasWiFi()) {
            return true;
        }
        if (item == FactoryTestItemsEnum.bluetooth && !DeviceAttr.getRunningDeviceAttr().hasBluetooth()) {
            return true;
        }

        if (item == FactoryTestItemsEnum.lightSensor && !DeviceAttr.getRunningDeviceAttr().hasLightSensor()) {
            return true;
        }
        return false;
    }


    ///////////////////////////////////////////////////////////////

    @Override
    public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
        FactoryTestItemsEnum itemsEnum = myGridAdapter.getItem(position);
        if (itemsEnum == null || itemsEnum.getItemClass() == null) {
            return;
        }

        if (itemsEnum == FactoryTestItemsEnum.aging) {
            if ((!FTUtils.isFactoryTestItemsAllPassedExcludeAging())) {
                showToast(getString(R.string.aging_item_clicked_while_others_not_tested));
                return;
            } else {
                SystemPropertyUtil.setSystemProperty(Constants.PERSIST_SYS_SHUTDOWN, "userReboot");
                AgingTestItemAttr.setAbnormalShutdownCount(mContext, 0);
            }
        }

        Intent intent = new Intent(mContext, itemsEnum.getItemClass());
//        if (EinkProperty.isDualScreen()) {
//            intent.putExtra(Constants.EXTRA_LAUNCH_SCREEN, Constants.EXTRA_LAUNCH_SCREEN_PANEL_A);
//        }
        startActivityForResult(intent, itemsEnum.getIdentify());

    }

    @Override
    public boolean onItemLongClick(AdapterView<?> adapterView, View view, int position,
                                   long id) {
        DebugLog.d("position = " + position + " id = " + id);
        FactoryTestItemsEnum itemsEnum = myGridAdapter.getItem(position);
        if (itemsEnum == null || itemsEnum.getItemClass() == null) {
            return true;
        }

        if (itemsEnum == FactoryTestItemsEnum.aging) {
            if (!FTUtils.isFactoryTestItemsAllPassedExcludeAging()) {
                showToast(getString(R.string.aging_item_clicked_while_others_not_tested));
                return true;
            } else {
                NumberPicker picker = new NumberPicker(mContext);
                picker.setMinValue(1);
                picker.setMaxValue(4);
                picker.setDescendantFocusability(NumberPicker.FOCUS_BLOCK_DESCENDANTS);
                picker.setDisplayedValues(Constants.NUMBER);

                FrameLayout layout = new FrameLayout(mContext);
                layout.addView(picker, new FrameLayout.LayoutParams(
                        FrameLayout.LayoutParams.WRAP_CONTENT,
                        FrameLayout.LayoutParams.WRAP_CONTENT,
                        Gravity.CENTER));

                new AlertDialog.Builder(mContext)
                        .setTitle(R.string.aging_times)
                        .setView(layout)
                        .setPositiveButton(android.R.string.ok, (dialogInterface, i) -> {
                            DebugLog.e("NumberPicker value = " + picker.getValue());
                            for (AgingTestItemAttr itemAttr : AgingTestItemAttr.values()) {
                                itemAttr.setRatioForTestOver(mContext, picker.getValue());
                            }
                            Intent intent = new Intent(mContext, itemsEnum.getItemClass());
                            startActivityForResult(intent, itemsEnum.getIdentify());
                        })
                        .setNegativeButton(android.R.string.cancel, null)
                        .show();
                return true;
            }
        } else if (itemsEnum == FactoryTestItemsEnum.first) {
            Intent intent = new Intent(mContext, ScreenOffsetActivity.class);
            startActivityForResult(intent, REQUEST_CODE_USING_BTN);
            return true;
        } else if (itemsEnum == FactoryTestItemsEnum.third) {
            Intent intent = new Intent(mContext, FactoryMicTestActivity.class);
            startActivityForResult(intent, REQUEST_CODE_USING_BTN);
            return true;

        } else return true;


    }


    private final static int COUNTS = 5;// 点击次数
    private final static long DURATION = 3000;// 规定有效时间
    private final static long DURATION2 = 2000;
    private long[] mHits = new long[COUNTS];
    private long[] third = new long[2];

    @Override
    public void onClick(View v) {

        if (v.getTag() instanceof Class) {
            startActivityUsingBtn((Class) v.getTag());
        } else if (v == txtSerialNo) {
            continuousClick();
        } else if (v == textView) {
            thirdClick();
        } else if (v == btnQuit) {
            LedCtrl_PX30.unControlLed();
            EinkUtils.setFastSleepTimeout("15");
            ShellUtils.execCommand(getString(R.string.force_stop_ft), false);
        }
    }

    private void thirdClick() {
        //每次点击时，数组向前移动一位
        System.arraycopy(third, 1, third, 0, third.length - 1);
        //为数组最后一位赋值
        third[third.length - 1] = SystemClock.uptimeMillis();
        if (third[0] >= (SystemClock.uptimeMillis() - DURATION2)) {
            btnEmmc.setVisibility(btnEmmc.getVisibility() == View.VISIBLE ? View.GONE : View.VISIBLE);
            btnMemoryTest.setVisibility(btnMemoryTest.getVisibility() == View.VISIBLE ? View.INVISIBLE : View.VISIBLE);
            btnEngineerTest.setVisibility(btnEngineerTest.getVisibility() == View.VISIBLE ? View.INVISIBLE : View.VISIBLE);
            if (!EinkProperty.isR2()) {
                btnQuit.setVisibility(btnQuit.getVisibility() == View.VISIBLE ? View.INVISIBLE : View.VISIBLE);
            }
            third = new long[2];
        }
    }

    private void continuousClick() {
        //每次点击时，数组向前移动一位
        System.arraycopy(mHits, 1, mHits, 0, mHits.length - 1);
        //为数组最后一位赋值
        mHits[mHits.length - 1] = SystemClock.uptimeMillis();
        if (mHits[0] >= (SystemClock.uptimeMillis() - DURATION)) {
//            showToast(getString(R.string.five_click));
            FTUtils.clearAgingResult(mContext);
            mHits = new long[COUNTS];//重新初始化数组
            myHandler.sendEmptyMessage(MyHandler.MSG_START_AGING);
        }
    }

    private final static int REQUEST_CODE_USING_BTN = 1;

    private void startActivityUsingBtn(Class<?> cls) {
        Intent intent = new Intent(mContext, cls);
        startActivityForResult(intent, REQUEST_CODE_USING_BTN);
        DebugLog.e("start " + cls);
    }

    private static class MyGridAdapter extends ArrayAdapter<FactoryTestItemsEnum> {

        private boolean useResultOfAfterAging;
        private Context mContext;

        MyGridAdapter(@NonNull Context context, int resource, @NonNull List<FactoryTestItemsEnum> objects) {
            super(context, resource, objects);
            useResultOfAfterAging = false;
            mContext = context;
        }

        boolean isUseResultOfAfterAging() {
            return useResultOfAfterAging;
        }

        void setUseResultOfAfterAging(boolean useResultOfAfterAging) {
            this.useResultOfAfterAging = useResultOfAfterAging;
        }

        @Override
        public View getView(final int position, @Nullable View convertView, @NonNull final ViewGroup parent) {

            ViewHolder holder = null;
            if (convertView != null) {
                holder = (ViewHolder) convertView.getTag();
            }

            if (holder == null) {
                holder = new ViewHolder();
                LayoutInflater inflater = (LayoutInflater) getContext().getSystemService(Context.LAYOUT_INFLATER_SERVICE);
                convertView = inflater.inflate(R.layout.item_test, null);
                holder.txtName = convertView.findViewById(R.id.txtName);
                holder.txtStatus = convertView.findViewById(R.id.txtStatus);
                holder.linearLayout = convertView.findViewById(R.id.ll_itemContainer);
                convertView.setTag(holder);
            }

            final FactoryTestItemsEnum itemsEnum = getItem(position);

            if (itemsEnum != null) {
                holder.txtName.setText(itemsEnum.getNameResId());
                String result = itemsEnum.getResult(mContext);
                if (mContext.getString(R.string.test_result_pass).equals(result)) {
                    holder.txtName.setTextColor(ContextCompat.getColor(mContext, R.color.gray_level_6));
                    holder.txtStatus.setTextColor(ContextCompat.getColor(mContext, R.color.gray_level_6));
                    holder.linearLayout.setBackgroundColor(ContextCompat.getColor(mContext, R.color.gray_level_f));
                } else {
                    holder.txtName.setTextColor(ContextCompat.getColor(mContext, R.color.gray_level_f));
                    holder.txtStatus.setTextColor(ContextCompat.getColor(mContext, R.color.gray_level_f));
                    holder.linearLayout.setBackgroundColor(ContextCompat.getColor(mContext, R.color.gray_level_2));
                }

                if (isUseResultOfAfterAging()) {
                    holder.txtStatus.setText(itemsEnum.getResultForAfterAging(mContext));

                } else {
                    holder.txtStatus.setText(itemsEnum.getResult(mContext));
                }
            }

            return convertView;
        }

    }

    private static final class ViewHolder {
        TextView txtName;
        TextView txtStatus;
        LinearLayout linearLayout;
    }

    private BatteryInfo.OnBatteryChangedListener onBatteryChangedListener =
            new BatteryInfo.OnBatteryChangedListener() {
                @Override
                public void onBatteryChangedListener(BatteryInfo info) {

                    BatteryCurrentThresholdEnum thresholdEnum = null;
                    for (BatteryCurrentThresholdEnum e : BatteryCurrentThresholdEnum.values()) {
                        if (e.isInRange(info.getBatteryLevel())) {
                            thresholdEnum = e;
                            break;
                        }
                    }

                    boolean pass = (thresholdEnum != null &&
                            (info.getBatteryCurrent_mAh() >= thresholdEnum.getCurrent() || info.getBatteryCurrent_mAh() < 0));

                    String result = getResultByCheckFactoryTestItemsEnum(FactoryTestItemsEnum.battery, pass);

                    String infoString = mContext.getString(R.string.ft_aging_battery_info2,
                            info.getBatteryVoltage(),
                            info.getBatteryLevel(),
                            info.getBatteryCapacity_mAh(),
                            info.getBatteryStatusString(),
                            info.getBatteryCurrent_mAh(), result);

                    SpannableString msp = getSpannableString(infoString);

                    txtBatteryInfo.setText(msp);

                }
            };

    private void registerAgingReceiver() {
        if (!mAgingReceiverTag) {
            IntentFilter filter = new IntentFilter(PCCommand.PC_ACTION_SET_AGING_ITEM_TEST_OVER_RATIO);
            mAgingReceiverTag = true;
            registerReceiver(AgingReceiver, filter);
        }
    }

    private void unregisterAgingReceiver() {
        if (mAgingReceiverTag) {
            mAgingReceiverTag = false;
            unregisterReceiver(AgingReceiver);
        }
    }

    private BroadcastReceiver AgingReceiver = new BroadcastReceiver() {
        @RequiresApi(api = Build.VERSION_CODES.O)
        @Override
        public void onReceive(Context context, Intent intent) {
            final String action = intent.getAction();
            if (action == null) {
                return;
            }

            if (PCCommand.PC_ACTION_SET_AGING_ITEM_TEST_OVER_RATIO.equals(action)) {
                myHandler.sendEmptyMessage(MainActivity.MyHandler.MSG_START_AGING);
            }
        }
    };

    ///////////////
    // sdcard end
    ///////////////

    private void startLedCtrl() {
        myHandler.sendEmptyMessage(MyHandler.MSG_LED_CTRL);
    }

    private void stopLedCtrl() {
        myHandler.removeMessages(MyHandler.MSG_LED_CTRL);
        LedCtrl_PX30.unControlLed();
    }

    private static final class MyHandler extends Handler {

        private final WeakReference<MainActivity> reference;

        private final static int MSG_LED_CTRL = 1000;
        private final static int PERIOD_LED_CTRL = 500;//2s

        private final static int MSG_CHECK_AGING = 2000;
        private final static int DELAY_CHECK_AGING = 2000;//1s

        private final static int MSG_START_AGING = 3000;

        private final static int MSG_GET_IMEI = 4000;
        private final static int DELAY_GET_IMEI = 5000;
        private final static int MSG_GET_MSISDN = 6000;
        private final static int DELAY_GET_MSISDN = 5000;


        private int ledOnCount = 0;

        MyHandler(MainActivity activity) {
            reference = new WeakReference<>(activity);
        }

        @RequiresApi(api = Build.VERSION_CODES.O)
        @Override
        public void handleMessage(Message msg) {
            MainActivity activity = reference.get();
            if (activity == null) {
                return;
            }

            switch (msg.what) {
                case MSG_GET_IMEI:
                    String imei = activity.getImeiNumber();
                    activity.txtImeiNo.setText(activity.getString(R.string.imeino, imei));
                    sendEmptyMessageDelayed(MyHandler.MSG_GET_IMEI, MyHandler.DELAY_GET_IMEI);
                    break;

                case MSG_GET_MSISDN:
                    String msisdn = getSimNumber(activity.mContext);
                    if(msisdn.isEmpty()){
                        activity.txtMsisdn.setText("getting...");
                        sendEmptyMessageDelayed(MyHandler.MSG_GET_MSISDN, MyHandler.DELAY_GET_MSISDN);
                    }else {
                        activity.txtMsisdn.setText(activity.getString(R.string.msisdn) + msisdn);
                    }
                    break;


                case MSG_START_AGING:

                    FactoryTestItemsEnum itemsEnum = FactoryTestItemsEnum.aging;
                    Intent intent = new Intent(activity.mContext, itemsEnum.getItemClass());
                    if (EinkProperty.isDualScreen()) {
                        intent.putExtra(Constants.EXTRA_LAUNCH_SCREEN, Constants.EXTRA_LAUNCH_SCREEN_PANEL_BOTH);
                    }
//                    intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_TASK_ON_HOME);
                    activity.startActivityForResult(intent, itemsEnum.getIdentify());
                    break;

                case MSG_CHECK_AGING:
                    activity.checkIfStartAging();
                    break;
                case MSG_LED_CTRL:

                    if (activity.batteryInfo.getBatteryLevel() >= HtfyunBuildConfig.STOP_LED_BATTERY_LEVEL) {
                        LedCtrl_PX30.setLed("g");
                        break;
                    }

                    if (++ledOnCount > 10000) {
                        ledOnCount = 0;
                    }

                    if (0 == (ledOnCount % 2)) {
                        LedCtrl_PX30.setLed("R");
                        LedCtrl_PX30.setLed("g");
                    } else {
                        LedCtrl_PX30.setLed("G");
                        LedCtrl_PX30.setLed("r");
                    }

                    sendEmptyMessageDelayed(msg.what, PERIOD_LED_CTRL);

                    break;
            }

        }

    }

    @Override
    public boolean dispatchKeyEvent(KeyEvent event) {
        int keyCode = event.getKeyCode();
        if (event.getAction() == KeyEvent.ACTION_DOWN) {
            switch (keyCode) {
                case KeyEvent.KEYCODE_POWER:
                    DebugLog.e("dispatchKeyEvent KEYCODE_POWER");
                    return true;

                case Constants.KEYCODE_DRAG:
                    DebugLog.e("dispatchKeyEvent KEYCODE_DRAG");
                    return true;

                case Constants.KEYCODE_REFRESH:
                    DebugLog.e("dispatchKeyEvent KEYCODE_REFRESH");
                    return true;

                case Constants.KEYCODE_SLIDE:
                    DebugLog.e("dispatchKeyEvent KEYCODE_SLIDE");
                    return true;

                default:
                    return super.dispatchKeyEvent(event);
            }
        }
        return super.dispatchKeyEvent(event);
    }


    ///////////////
    // sdcard start
    ///////////////
/*    private String getSDCardPath() {
        if (!isSDCardInserted()) {
            return "";
        }

        StorageManager sm = getSystemService(StorageManager.class);

        if (sm == null) {
            return "";
        }

        List<StorageVolume> volList = sm.getStorageVolumes();
        if (volList.isEmpty()) {
            return "";
        }

        for (StorageVolume vol : volList) {
            if (vol.getState().equals(Environment.MEDIA_MOUNTED) && vol.isRemovable()) {
                DebugLog.i("desc = " + vol.getDescription(mContext) + ", StoragePath---> " + vol.getPath());
                return vol.getPath();
            }
        }
        return "";

    }*/

/*    private boolean isSDCardInserted() {

        StorageManager sm = getSystemService(StorageManager.class);

        if (sm == null) {
            return false;
        }

        List<StorageVolume> volList = sm.getStorageVolumes();
        if (volList.isEmpty()) {
            return false;
        }

        for (StorageVolume vol : volList) {

            DebugLog.i("vol state = " + vol.getState() + ", desc = " + vol.getDescription(mContext));

        }

        for (StorageVolume vol : volList) {
            if (vol.getState().equals(Environment.MEDIA_MOUNTED)
                    && vol.isRemovable()) {

                return true;
            }
        }

        return false;

    }*/

/*    private void updateUIWhileSDCardMounted() {
        txtSdcardInfo.setText(R.string.sdcard_test_ejected);
        if (!isSDCardInserted()) {
            return;
        }

        String path = getSDCardPath();
        if (TextUtils.isEmpty(path)) {
            return;
        }

        StatFs stat = new StatFs(path);

        String result = getResultByCheckFactoryTestItemsEnum(FactoryTestItemsEnum.sdcard, true);

        String infoString = mContext.getString(R.string.sdcard_test_inserted_info,
                Formatter.formatFileSize(mContext, stat.getTotalBytes()),
                Formatter.formatFileSize(mContext, stat.getFreeBytes()),
                result);

        SpannableString msp = getSpannableString(infoString);

        txtSdcardInfo.setText(msp);

        FactoryTestItemsEnum.sdcard.setResult(mContext, getString(R.string.test_result_pass));
//        unregisterSdcardReceiver();

    }*/

/*    private IntentFilter getIntentFilterOfSDCard() {
        IntentFilter intentFilter = new IntentFilter(Intent.ACTION_MEDIA_MOUNTED);

        intentFilter.addAction(Intent.ACTION_MEDIA_UNMOUNTED);

        intentFilter.addAction(Intent.ACTION_MEDIA_REMOVED);
        intentFilter.addAction(Intent.ACTION_MEDIA_BAD_REMOVAL);

        intentFilter.addDataScheme("file");

        return intentFilter;
    }*/

/*    private void registerSdcardReceiver() {
        if (!deviceAttr.hasSDCard()) {
            return;
        }
        if (!mSDReceiverTag) {
            mSDReceiverTag = true;
            mContext.registerReceiver(sdcardReceiver, getIntentFilterOfSDCard());
        }

    }*/

/*    private void unregisterSdcardReceiver() {
        if (!deviceAttr.hasSDCard()) {
            return;
        }
        if (mSDReceiverTag) {
            mSDReceiverTag = false;
            mContext.unregisterReceiver(sdcardReceiver);
        }
    }*/


/*    private final BroadcastReceiver sdcardReceiver = new BroadcastReceiver() {

        @Override
        public void onReceive(Context context, Intent intent) {
            final String action = intent.getAction();
            if (action == null) {
                return;
            }
            DebugLog.e("sdcard action = " + action + ", intent.getData() = " + intent.getData());

            updateUIWhileSDCardMounted();

        }
    };*/

}
